package com.cc;

import com.cc.domain.Person;
import com.cc.domain.User;
import com.cc.service.UserService;
import org.springframework.aop.aspectj.annotation.SimpleMetadataAwareAspectInstanceFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.stereotype.Controller;

import java.io.IOException;
import java.util.Set;
import java.util.function.Supplier;

/**
 * @title: Main
 * @author: lbj
* @date: 2022/5/4 9:47 下午
 * @description: TODO 类描述
 */

@Controller
//@SpringBootApplication
public class Main {
    public static void main(String[] args) throws IOException {
        final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        System.out.println(context.getBean(UserService.class));
        System.out.println(context.getBean(UserService.class));
        System.out.println(context.getBean(UserService.class));

//        context.close();

//        BeanDefinitionReader
    }

    private static void MetadataReaderTest() throws IOException {
        final SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();

        final MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.cc.service.UserService");
        final ClassMetadata classMetadata = metadataReader.getClassMetadata();
        System.out.println(classMetadata);

        final AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        for (String annotationType : annotationMetadata.getAnnotationTypes()) {
            System.out.println(annotationType);
        }

        final Set<MethodMetadata> annotatedMethods = annotationMetadata.getAnnotatedMethods(Bean.class.getName());
        for (MethodMetadata annotatedMethod : annotatedMethods) {
            System.out.println(annotatedMethods);
        }
    }

    private static void eventTest(AnnotationConfigApplicationContext context) {
//        context.publishEvent("new PayloadApplicationEvent<String>()");
//
//        final UserService bean = context.getBean(UserService.class);
//        bean.test();


//        System.out.println(context.getMessage("test", null, new Locale("en")));
//
//        final ConfigurableEnvironment environment = context.getEnvironment();
//
//        System.out.println(environment.getSystemProperties());
//        System.out.println(environment.getSystemEnvironment());
//        System.out.println(environment.getPropertySources());

        //        final UserService bean = context.getBean(UserService.class);
//        bean.test();
//        bean.test2();

//        System.out.println(context.getBean(OrderService.class));
//        System.out.println(context.getBean(OrderService.class));
//        System.out.println(context.getBean(OrderService.class));
    }

    private static void test3(AnnotationConfigApplicationContext context) {
        //        final UserService userService = context.getBean("USERSERVICE", UserService.class);
        final UserService userService = context.getBean(UserService.class);
        System.out.println(userService);
//        userService.test();
//        userService.test();

//        System.out.println(context.getBean(OrderService.class));
//        System.out.println(context.getBean("orderService1"));
//        System.out.println(context.getBean("orderService2"));
    }

    private static void componentTest(AnnotationConfigApplicationContext context) {
        //        final UserService userService = context.getBean(UserService.class);
//        userService.test();
//        final OrderService orderService = context.getBean("orderService", OrderService.class);
//        System.out.println(orderService);
        //  com.cc.service.UserService=org.springframework.stereotype.Component
        System.out.println(context.getBean("userService"));
        System.out.println(context.getBean("orderService"));
    }

    private static void getUserTest(AnnotationConfigApplicationContext context) {
        System.out.println(context.getBean(AppConfig.class));

        UserService userService = context.getBean(UserService.class);
        System.out.println(userService);

        userService = context.getBean(UserService.class);
        System.out.println(userService);

        userService = context.getBean(UserService.class);
        System.out.println(userService);
    }

    private static void appContextTest() {
        //        SpringApplication.run(Main.class,args);

//        final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

        final AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setBeanClass(User.class);
        context.registerBeanDefinition("user", beanDefinition);

        context.refresh();

        System.out.println(context.getEnvironment().getSystemEnvironment());
        System.out.println(context.getEnvironment().getSystemProperties());

        final Resource resource = context.getResource("bd.xml");
        System.out.println(resource);

        final User user = context.getBean("user", User.class);
        System.out.println(user);
    }

    private static void singleBean() {
        final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        context.refresh();

        System.out.println(context.getBean("user", User.class));
        System.out.println(context.getBean("user", User.class));
        System.out.println(context.getBean("user1", User.class));
        System.out.println(context.getBean("user1", User.class));
    }

    private static void createBean2(AnnotationConfigApplicationContext context) {
        context.registerBean(User.class, new Supplier<User>() {
            @Override
            public User get() {
                final User user = new User();
                user.setName("xxx");
                return user;
            }
        });
        context.refresh();

        final User user = context.getBean("user", User.class);
        System.out.println(user);
        System.out.println(user.getName());
    }

    private static void test1() {
        final AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

//        final AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
//        beanDefinition.setBeanClass(UserFactoryBean.class);
//        applicationContext.registerBeanDefinition("user",beanDefinition);
//        applicationContext.refresh();

//        UserFactoryBean user = applicationContext.getBean("&user", UserFactoryBean.class);
//        final Person user = applicationContext.getBean("user", Person.class);
        final Person user = applicationContext.getBean(Person.class);
        System.out.println(user);
    }
}
